package com.shujuwuliankeji.ems.cloud.module.bussiness.service.impl;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.github.cm.heclouds.onenet.studio.api.IotClient;
import com.github.cm.heclouds.onenet.studio.api.entity.Meta;
import com.github.cm.heclouds.onenet.studio.api.entity.application.project.DeviceInfo;
import com.github.cm.heclouds.onenet.studio.api.entity.application.project.QueryDeviceListResponse;
import com.shujuwuliankeji.ems.cloud.common.core.exception.GlobalException;
import com.shujuwuliankeji.ems.cloud.common.core.utils.DateUtils;
import com.shujuwuliankeji.ems.cloud.common.security.annotation.SaaS;
import com.shujuwuliankeji.ems.cloud.common.security.utils.SecurityUtils;
import com.shujuwuliankeji.ems.cloud.module.bussiness.constant.DeviceTypeEnum;
import com.shujuwuliankeji.ems.cloud.module.bussiness.domain.BussDevice;
import com.shujuwuliankeji.ems.cloud.module.bussiness.domain.BussProject;
import com.shujuwuliankeji.ems.cloud.module.bussiness.domain.BussProjectNode;
import com.shujuwuliankeji.ems.cloud.module.bussiness.domain.vo.ProjectDeviceSummaryVO;
import com.shujuwuliankeji.ems.cloud.module.bussiness.iot.IotClientUtils;
import com.shujuwuliankeji.ems.cloud.module.bussiness.iot.extend.QueryProjectDeviceListRequest;
import com.shujuwuliankeji.ems.cloud.module.bussiness.mapper.BussDeviceAmmeterDataMapper;
import com.shujuwuliankeji.ems.cloud.module.bussiness.mapper.BussDeviceMapper;
import com.shujuwuliankeji.ems.cloud.module.bussiness.mapper.BussDeviceWatermeterDataMapper;
import com.shujuwuliankeji.ems.cloud.module.bussiness.service.IBussDeviceService;
import com.shujuwuliankeji.ems.cloud.module.bussiness.service.IBussProjectNodeService;
import com.shujuwuliankeji.ems.cloud.module.bussiness.service.IBussProjectService;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;

/**
 * 设备管理Service业务层处理
 * 
 * @author fanzhongjie
 * @date 2023-01-30
 */
@Service
public class BussDeviceServiceImpl implements IBussDeviceService {
	@Autowired
	private BussDeviceMapper bussDeviceMapper;

	@Autowired
	private IBussProjectNodeService nodeService;

	@Autowired
	private IotClientUtils iotClientUtils;

	@Autowired
	private IBussProjectService projectService;

	@Autowired
	private BussDeviceAmmeterDataMapper ammeterDataMapper;

	@Autowired
	private BussDeviceWatermeterDataMapper watermeterMapper;

	/**
	 * 查询设备管理
	 * 
	 * @param id 设备管理主键
	 * @return 设备管理
	 */
	@Override
	@SaaS
	public BussDevice selectBussDeviceById(BussDevice bussDevice) {
		return bussDeviceMapper.selectBussDeviceById(bussDevice);
	}

	/**
	 * 查询设备管理列表
	 * 
	 * @param bussDevice 设备管理
	 * @return 设备管理
	 */
	@Override
	@SaaS
	public List<BussDevice> selectBussDeviceList(BussDevice bussDevice) {
		return bussDeviceMapper.selectBussDeviceList(bussDevice);
	}

	/**
	 * 新增设备管理
	 * 
	 * @param bussDevice 设备管理
	 * @return 结果
	 */
	@Override
	@SaaS
	public int insertBussDevice(BussDevice bussDevice) {
		bussDevice.setCreateTime(DateUtils.getNowDate());
		return bussDeviceMapper.insertBussDevice(bussDevice);
	}

	/**
	 * 修改设备管理
	 * 
	 * @param bussDevice 设备管理
	 * @return 结果
	 */
	@SaaS
	@Override
	public int updateBussDevice(BussDevice bussDevice) {
		bussDevice.setUpdateTime(DateUtils.getNowDate());
		return bussDeviceMapper.updateBussDevice(bussDevice);
	}

	/**
	 * 批量删除设备管理
	 * 
	 * @param ids 需要删除的设备管理主键
	 * @return 结果
	 */
	@SaaS
	@Override
	public int deleteBussDeviceByIds(BussDevice bussDevice) {
		return bussDeviceMapper.deleteBussDeviceByIds(bussDevice);
	}

	/**
	 * 删除设备管理信息
	 * 
	 * @param id 设备管理主键
	 * @return 结果
	 */
	@Override
	@SaaS
	public int deleteBussDeviceById(BussDevice bussDevice) {
		return bussDeviceMapper.deleteBussDeviceById(bussDevice);
	}

	@Override
	@SaaS
	public List<BussDevice> selectBussTopologyDeviceList(BussDevice bussDevice) {
		return bussDeviceMapper.selectBussTopologyDeviceList(bussDevice);
	}

	@Override
	@SaaS
	public List<BussDevice> selectBussNonTopologyDeviceList(BussDevice bussDevice) {
		return bussDeviceMapper.selectBussNonTopologyDeviceList(bussDevice);
	}

	@Override
	@SaaS
	public int addDeviceToTopology(BussDevice bussDevice) {
		Long[] ids = bussDevice.getIds();
		if (ids == null || ids.length == 0) {
			throw new GlobalException("请选择要添加的设备。");
		}
		bussDevice.setUpdateTime(DateUtils.getNowDate());
		bussDevice.setUpdateBy(SecurityUtils.getUsername());
		// 查询node祖级列表
		BussProjectNode tempNode = new BussProjectNode();
		tempNode.setId(bussDevice.getNodeId());
		BussProjectNode node = nodeService.selectBussProjectNodeById(tempNode);
		if (node == null) {
			throw new GlobalException("当前项目节点不存在，请刷新项目数据。");
		}
		bussDevice.setAncestors(node.getAncestors() + "," + bussDevice.getNodeId());
		return bussDeviceMapper.addDeviceToTopology(bussDevice);
	}

	@Override
	@SaaS
	public int removeTopology(BussDevice device) {
		Long[] ids = device.getIds();
		if (ids == null || ids.length == 0) {
			throw new GlobalException("请选择要移除的设备。");
		}
		device.setUpdateTime(DateUtils.getNowDate());
		device.setUpdateBy(SecurityUtils.getUsername());
		return bussDeviceMapper.removeTopology(device);
	}

	@Override
	public boolean checkDeviceExist(BussDevice checkDevice) {
		return bussDeviceMapper.checkDeviceExist(checkDevice) > 0;
	}

	@Override
	public int insertBussDeviceBatch(List<BussDevice> list) {
		return bussDeviceMapper.insertBussDeviceBatch(list);
	}

	@Override
	public void poll(Long companyId, DeviceTypeEnum ammeter) {

		IotClient iotClient = iotClientUtils.getClient(companyId);
		// 查询企业下项目水表分组ID和应用项目ID
		List<BussProject> projects = projectService.selectBussProjectAllByCompanyId(companyId);
		if (CollUtil.isNotEmpty(projects)) {
			projects.forEach(project -> {
				if (StrUtil.isNotEmpty(project.getIotProjectId())) {
					// 查询偏移量
					int offset = 0;
					// 查询条数
					int pageSize = 100;
					// 总页数 需计算
					int totalPage = 0;

					QueryProjectDeviceListRequest request = new QueryProjectDeviceListRequest();
					request.setGroupId("null");// 赋值默认字符串，无法查出数据
					switch (ammeter) {
					case AMMETER:

						if (StrUtil.isNotBlank(project.getAmmeterGroupId())) {
							request.setGroupId(project.getAmmeterGroupId());
						}

						break;
					case WATERMETER:
						if (StrUtil.isNotBlank(project.getWatermeterGroupId())) {
							request.setGroupId(project.getWatermeterGroupId());
						}
						break;
					default:
						break;
					}
					request.setProjectId(project.getIotProjectId());
					request.setOffset(offset);
					request.setLimit(1);
					QueryDeviceListResponse response = null;
					// 查询返回total
					try {
						response = iotClient.sendRequest(request);
						Meta meta = response.getMeta();
						if (meta.getTotal() > 0) {
							totalPage = meta.getTotal() % pageSize == 0 ? meta.getTotal() / pageSize
									: (meta.getTotal() / pageSize) + 1;
						}
					} catch (Exception e) {
						e.printStackTrace();
					}
					// 循环拉拉取数据
					if (totalPage > 0) {
						for (int i = 0; i < totalPage; i++) {
							request.setOffset(i * pageSize);
							request.setLimit(pageSize);
							try {
								response = iotClient.sendRequest(request);
								List<DeviceInfo> devices = response.getList();
								transferToDababase(project, devices);
							} catch (Exception e) {
								e.printStackTrace();
							}
						}
					}
				}
			});

		}
		try {
			iotClient.close();
		} catch (IOException e) {
		}
	}

	/**
	 * 将数据传入到数据库中
	 * 
	 * @param devices
	 */
	private void transferToDababase(BussProject project, List<DeviceInfo> devices) {
		List<BussDevice> list = new ArrayList<>();
		// 先判断数据库中是否有该设备数据productId deviceName
		devices.forEach(device -> {
			BussDevice checkDevice = new BussDevice();
			checkDevice.setCompanyId(project.getCompanyId());
			checkDevice.setProjectId(project.getId());
			checkDevice.setIotProjectId(project.getIotProjectId());
			checkDevice.setDeviceName(device.getDeviceName());
			checkDevice.setProductId(device.getProductId());
			checkDevice.setStatus(device.getStatus().getValue());
			checkDevice.setCreateBy(SecurityUtils.getUsername());
			checkDevice.setCreateTime(device.getCreatedTime());
			checkDevice.setNodeType(device.getNodeType().getValue());
			checkDevice.setLastTime(DateUtil.format(device.getLastTime(), "yyyy-MM-dd HH:mm:ss"));
			checkDevice.setProductName(device.getProductName());
			checkDevice.setDeviceType(1);// 1 水表
			if (!checkDeviceExist(checkDevice)) {
				list.add(checkDevice);
			}
		});
		if (CollUtil.isNotEmpty(list)) {
			insertBussDeviceBatch(list);
		}
	}

	@Override
	@SaaS
	public ProjectDeviceSummaryVO projectSummary(BussDevice device) {
		ProjectDeviceSummaryVO vo = new ProjectDeviceSummaryVO();
		double finalData = 0;
		int onlineCount = bussDeviceMapper.selectOnlineCount(device);
		int totalCount = bussDeviceMapper.selectDeviceCount(device);
		if (DeviceTypeEnum.AMMETER.getValue().equals(device.getDeviceType())) {
			// 查询今日总能耗
			Double yesterdayData = ammeterDataMapper.selectDataByDate(device.getCompanyId(), device.getProjectId(),
					DateUtil.format(DateUtil.yesterday(), "yyyy-MM-dd"));
			// 查询今日总能耗
			Double todayData = ammeterDataMapper.selectDataByDate(device.getCompanyId(), device.getProjectId(),
					DateUtil.format(DateUtils.getNowDate(), "yyyy-MM-dd"));
			if (todayData != null && yesterdayData != null) {
				finalData = todayData - yesterdayData;
			}
		} else if (DeviceTypeEnum.WATERMETER.getValue().equals(device.getDeviceType())) {
			// 查询今日总能耗
			Double yesterdayData = watermeterMapper.selectDataByDate(device.getCompanyId(), device.getProjectId(),
					DateUtil.format(DateUtil.yesterday(), "yyyy-MM-dd"));
			// 查询今日总能耗
			Double todayData = watermeterMapper.selectDataByDate(device.getCompanyId(), device.getProjectId(),
					DateUtil.format(DateUtils.getNowDate(), "yyyy-MM-dd"));
			if (todayData != null && yesterdayData != null) {
				finalData = todayData - yesterdayData;
			}
		}
		vo.setDeviceOnlineTotal(onlineCount);
		vo.setDeviceTotal(totalCount);
		vo.setEnergyConsumption(finalData);
		return vo;
	}

}
